package com.jiazixuan.stock.service.impl;

import com.jiazixuan.stock.exception.BusinessException;
import com.jiazixuan.stock.mapper.SysPermissionMapper;
import com.jiazixuan.stock.mapper.SysRolePermissionMapper;
import com.jiazixuan.stock.pojo.domain.MenusPermDomain;
import com.jiazixuan.stock.pojo.domain.SysPermissionDomain;
import com.jiazixuan.stock.pojo.entity.SysPermission;
import com.jiazixuan.stock.service.PermissionService;
import com.jiazixuan.stock.utils.IdWorker;
import com.jiazixuan.stock.vo.req.PermissionAddVo;
import com.jiazixuan.stock.vo.resp.R;
import com.jiazixuan.stock.vo.resp.ResponseCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class PermissionServiceImpl implements PermissionService {
    @Autowired
    private SysPermissionMapper sysPermissionMapper;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private SysRolePermissionMapper sysRolePermissionMapper;
    /**
     * 查询所有权限集合
     */
    @Override
    public R<List<SysPermission>> getAllPermissions() {
        //查询所有权限
        List<SysPermission> allPermission = sysPermissionMapper.getAllPermission();
        //使用递归形成权限树
        List<MenusPermDomain> menusPermDomains = MenusPermDomain.digui2(allPermission, 0l);
        return R.ok(allPermission);
    }

    /**
     *  添加权限时回显权限树，仅仅显示目录和菜单
     */
    @Override
    public R<List<SysPermissionDomain>> getPermissionsTree() {
        //查询所有的权限
        List<SysPermission> allPermission = sysPermissionMapper.getAllPermission();
        //创建集合用于接受要返回的数据
        List<SysPermissionDomain> permsTreeList = new ArrayList<>();
        //向集合中添加一个顶级菜单
        permsTreeList.add(SysPermissionDomain.builder().id(0l).title("顶级菜单").level(0).build());
        //使用递归逐级将全部权限添加到集合中
        permsTreeList.addAll(getPermissionLevelTree(allPermission,0l,1));
        if(CollectionUtils.isEmpty(permsTreeList)){
            return R.error(ResponseCode.DATA_ERROR);
        }
        return R.ok(permsTreeList);
    }

    /**
     * 权限添加按钮
     */
    @Override
    public R addPer(PermissionAddVo vo) {
        //创建权限对象
        SysPermission sysPermission = new SysPermission();
        //将传来的vo对象复制到创建的权限对象中
        BeanUtils.copyProperties(vo,sysPermission);
        //判断该权限对象是否符合规范
        checkPermissionForm(sysPermission);
        sysPermission.setId(idWorker.nextId());
        int i=sysPermissionMapper.addPerms(sysPermission);
        if(i>0){
            return R.ok("添加成功");
        }
        else return R.error(ResponseCode.DATA_ERROR.getMessage());

    }

    /**
     * 更新权限
     */
    @Override
    public R updatePer(PermissionAddVo vo) {
        //创建权限对象
        SysPermission sysPermission = new SysPermission();
        //将传来的vo对象复制到创建的权限对象中
        BeanUtils.copyProperties(vo,sysPermission);
        //判断该权限对象是否符合规范
        checkPermissionForm(sysPermission);
        int i=sysPermissionMapper.updatePerms(sysPermission);
        if(i>0){
            return R.ok("添加成功");
        }
        else return R.error(ResponseCode.DATA_ERROR.getMessage());
    }

    /**
     * 删除权限
     */
    @Override
    public R deletePer(String permissionId) {
        //判断该权限是否有子权限，有则删除失败
        int count =this.sysPermissionMapper.findChildrenCountByParentId(permissionId);
        if (count>0) {
            throw new BusinessException(ResponseCode.ROLE_PERMISSION_RELATION.getMessage());
        }
        //删除该权限与角色的关系
        this.sysRolePermissionMapper.deleteByPermissionId(permissionId);
        //更新状态为已删除
        SysPermission permission = SysPermission.builder().id(Long.parseLong(permissionId)).deleted(0).updateTime(new Date()).build();
        int updateCount = this.sysPermissionMapper.updateByPrimaryKeySelective(permission);
        if (updateCount!=1) {
            throw new BusinessException(ResponseCode.ERROR.getMessage());
        }
        return R.ok(ResponseCode.SUCCESS.getMessage());
    }

    /**
     * 递归设置级别，用于权限列表 添加/编辑 所属菜单树结构数据
     */
    private List<SysPermissionDomain> getPermissionLevelTree(List<SysPermission> permissions,Long parentId,Integer level){
        ArrayList<SysPermissionDomain> list = new ArrayList<>();
        for (SysPermission permission : permissions) {
            if(permission.getType().intValue()!=3 && permission.getPid().equals(parentId)){
                SysPermissionDomain nodeTreevo = new SysPermissionDomain();
                nodeTreevo.setId(permission.getId());
                nodeTreevo.setTitle(permission.getTitle());
                nodeTreevo.setLevel(permission.getType());
                list.add(nodeTreevo);
                list.addAll(getPermissionLevelTree(permissions,permission.getId(),level+1));
            }
        }
        return list;
    }

    /**
     * 检查添加或者更新的权限提交表单是否合法，如果不合法，则直接抛出异常
     * 检查规则：目录的父目录等级必须为0或者其他目录（等级为1）
     *          菜单的父父级必须是1，也就是必须是父目录，
     *          按钮的父级必须是菜单，也是是等级是3，且父级是2
     *          其他关联的辨识 url等信息也可做相关检查
     * @param vo
     */
    private void checkPermissionForm(SysPermission vo) {
        if (vo!=null || vo.getType()!=null || vo.getPid()!=null){
            //获取权限类型 0：顶级目录 1.普通目录 2.菜单 3.按钮
            Integer type = vo.getType();
            //获取父级id
            Long pid = vo.getPid();
            //根据父级id查询父级信息
            SysPermission parentPermission = this.sysPermissionMapper.selectByPrimaryKey(pid);
            if (type==1){
                if(!pid.equals(0L) || (parentPermission!=null && parentPermission.getType()> 1)){
                    throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_CATALOG_ERROR.getMessage());
                }
            }
            else if (type==2){
                if (parentPermission==null || parentPermission.getType() !=1 ){
                    throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_CATALOG_ERROR.getMessage());
                }
                if (StringUtils.isBlank(vo.getUrl())){
                    throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_URL_CODE_NULL.getMessage());
                }
            }
            else if (type==3){
                if (parentPermission==null || parentPermission.getType()!=2){
                    throw new BusinessException(ResponseCode.OPERATION_MENU_PERMISSION_BTN_ERROR.getMessage());
                }
                else if (vo.getUrl()==null || vo.getCode()==null || vo.getMethod()==null){
                    throw new BusinessException(ResponseCode.DATA_ERROR.getMessage());
                }
            }
            else {
                throw new BusinessException(ResponseCode.DATA_ERROR.getMessage());
            }
        }else {
            throw new BusinessException(ResponseCode.DATA_ERROR.getMessage());
        }
    }
}
